/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import java.util.Random;

import junit.framework.TestCase;


/**
 * Performs Validation Test for url validations.
 *
 * @version $Revision: 1128446 $ $Date: 2011-05-27 13:29:27 -0700 (Fri, 27 May 2011) $
 */

public class UrlValidatorTest extends TestCase 
{

	private boolean printStatus = false;
	private boolean printIndex = false;//print index that indicates current scheme,host,port,path, query test were using.

	public UrlValidatorTest(String testName) 
	{
      		super(testName);
   	}


	/*
	    Right now tests 4 different URLs.  The last URL fails the test.  The bug report for this test is in URLValidator.pdf
	*/   
   
   	public void testManualTest()
   	{
		UrlValidator urlVal = new UrlValidator(null, null, UrlValidator.ALLOW_ALL_SCHEMES);
	   	System.out.println("Should be true: " + urlVal.isValid("http://www.amazon.com"));
		System.out.println("Should be false: " + urlVal.isValid("facebook.com.com"));
		System.out.println("Should be false: " + urlVal.isValid("www.amazon.ccc"));
		//The following is a google map for Oregon State University.o
		System.out.println("Should be true: " + urlVal.isValid("https://www.google.com/maps/preview?ie=UTF-8&fb=1&gl=us&sll=44.563781,-123.279444&sspn=0.187876,0.3516211&cid=12033602656585364639&q=Oregon+State+University&ei=ItsEVN3BLMLJgwSUu4GQCg&ved=0CIYBEPwSMA0"));
	}
      
   	public void testYourFirstPartition()
   	{
		UrlValidator urlVal = new UrlValidator(null, null, UrlValidator.ALLOW_LOCAL_URLS);
		System.out.println("[TESTING] DomainValidator Partioning by functions...");
	   	System.out.println("Testing .com generic Should be true: " + urlVal.isValid("http://www.amazon.com"));
	   	System.out.println("Testing .con generic Should be false: " + urlVal.isValid("http://www.amazon.con"));
	   	System.out.println("Testing .arpa infrastructure Should be true: " + urlVal.isValid("http://www.amazon.arpa"));
	   	System.out.println("Testing .arpaa infrastructure Should be false: " + urlVal.isValid("http://www.amazon.arpaa"));
	   	System.out.println("Testing .ac country Should be true: " + urlVal.isValid("http://www.amazon.ac"));
	   	System.out.println("Testing .ab country Should be false: " + urlVal.isValid("http://www.amazon.ab"));
	   	//BUG (In DomainValidator line 204, should remove !
	   	System.out.println("Testing localhost Should be true: " + urlVal.isValid("http://localhost"));  	
   	}
   
   	public void testYourSecondPartition()
	{
	   	 UrlValidator urlVal = new UrlValidator(null, null, UrlValidator.ALLOW_ALL_SCHEMES);
       System.out.println("[TESTING] Partioning by only altering hostnames, testing illegal characters...");
	   	System.out.println("Testing control Should be true: " + urlVal.isValid("http://www.amazon.com"));
	   	System.out.println("Testing : character Should be false: " + urlVal.isValid("http://www.ama:zon.com"));
	   	System.out.println("Testing / character Should be false: " + urlVal.isValid("http://www.ama/zon.com"));
	   	System.out.println("Testing # character Should be false: " + urlVal.isValid("http://www.ama#zon.com"));
	   	System.out.println("Testing ? character Should be false: " + urlVal.isValid("http://www.ama?zon.com"));
	   	System.out.println("Testing & character Should be false: " + urlVal.isValid("http://www.ama&zon.com"));
	   	System.out.println("Testing @ character Should be false: " + urlVal.isValid("http://www.ama@zon.com"));
	   	System.out.println("Testing % character Should be false: " + urlVal.isValid("http://www.ama%zon.com"));
	   	System.out.println("Testing + character Should be false: " + urlVal.isValid("http://www.ama+zon.com"));
	   	System.out.println("Testing space character Should be false: " + urlVal.isValid("http://www.ama zon.com"));
	   	System.out.println("Testing ; character Should be false: " + urlVal.isValid("http://www.ama;zon.com"));
	   	System.out.println("Testing = character Should be false: " + urlVal.isValid("http://www.ama=zon.com"));
	   	System.out.println("Testing $ character Should be false: " + urlVal.isValid("http://www.ama$zon.com"));
	   	System.out.println("Testing , character Should be false: " + urlVal.isValid("http://www.ama,zon.com"));
	   	System.out.println("Testing < character Should be false: " + urlVal.isValid("http://www.ama<zon.com"));
	   	System.out.println("Testing > character Should be false: " + urlVal.isValid("http://www.ama>zon.com"));
	   	System.out.println("Testing ~ character Should be false: " + urlVal.isValid("http://www.ama~zon.com"));
	   	System.out.println("Testing ^ character Should be false: " + urlVal.isValid("http://www.ama^zon.com"));
	   	System.out.println("Testing ' character Should be false: " + urlVal.isValid("http://www.ama'zon.com"));
	   	System.out.println("Testing \\ character Should be false: " + urlVal.isValid("http://www.ama\\zon.com"));
	   	System.out.println("Testing [ character Should be false: " + urlVal.isValid("http://www.ama[zon.com"));
	   	System.out.println("Testing ] character Should be false: " + urlVal.isValid("http://www.ama]zon.com"));
	   	System.out.println("Testing { character Should be false: " + urlVal.isValid("http://www.ama{zon.com"));
	   	System.out.println("Testing } character Should be false: " + urlVal.isValid("http://www.ama}zon.com"));
	   	System.out.println("Testing | character Should be false: " + urlVal.isValid("http://www.ama|zon.com"));
	   	System.out.println("Testing \" character Should be false: " + urlVal.isValid("http://www.ama\"zon.com"));
   	}
   
   
   	public void testIsValid()
	{  
		//Test URLs we expect to be false
   	   	UrlValidator urlVal = new UrlValidator(null, null, UrlValidator.ALLOW_ALL_SCHEMES);
   	   	Random rand = new Random();
   	   	String address = "amazon";
	   	String[] prefixes = {"htp://", "http://ww.", "ww.", "w.", "ww"};
	   	int numPrefixes = prefixes.length;
	   	String[] suffixes = {".", ".abc", "//", "", "ccc", ".edu.edu"};
	   	int numSuffixes = suffixes.length;
	   
	   	for(int i = 0;i<10000;i++)
	   	{
			String prefix = prefixes[rand.nextInt(numPrefixes - 1)];
		   	String suffix = suffixes[rand.nextInt(numSuffixes - 1)];
		   	String testURL;
		   	testURL = prefix + address + suffix;
		   	assertFalse(urlVal.isValid(testURL));   
	   	}
	   	System.out.println("unit test passed");
   	}
   
   	public void testAnyOtherUnitTest()
   	{
   		UrlValidator urlVal = new UrlValidator(null, null, UrlValidator.ALLOW_ALL_SCHEMES);
   		String urlToTest;
   		String urlToTestOpts;
   		boolean verify = true;
   		
		for(int i = 0;i<10000;i++)
	   	{//randomly making URLS
			int schemeIndex = (int)(Math.random()*scheme.length);
			int portIndex = (int)(Math.random()*port.length);
            int pathIndex = (int)(Math.random()*path.length);
            int queryIndex = (int)(Math.random()*query.length);
            int pathOptsIndex = (int)(Math.random()*pathOptions.length);
            int authorityIndex = (int)(Math.random()*authority.length);

            
            
            //Creating LINK
            urlToTest = urlToTestOpts = null;
            urlToTest = scheme[schemeIndex][0]+authority[authorityIndex][0]+port[portIndex][0]+path[pathIndex][0]+query[queryIndex][0];
            urlToTestOpts = scheme[schemeIndex][0]+authority[authorityIndex][0]+port[portIndex][0]+pathOptions[pathOptsIndex][0]+query[queryIndex][0];
	   	
            //This is where built URLs are actually tested
            boolean resultForUrl = urlVal.isValid(urlToTest);
            boolean resultForOpts = urlVal.isValid(urlToTestOpts);
            
            if ((Boolean.valueOf(query[queryIndex][1]) && Boolean.valueOf(scheme[schemeIndex][1]) && Boolean.valueOf(authority[authorityIndex][1]) && Boolean.valueOf(port[portIndex][1]) && Boolean.valueOf(path[pathIndex][1]))==resultForUrl){
            	
            	System.out.println(urlToTest + " PASSED");
            	
        }else{
        	//this means that the expected is not equal to the tested val; FAILURE
                System.out.println(urlToTest + " FAILED");
                verify = false;
        }
            
            if ((Boolean.valueOf(query[queryIndex][1]) && Boolean.valueOf(scheme[schemeIndex][1]) && Boolean.valueOf(authority[authorityIndex][1]) && Boolean.valueOf(port[portIndex][1]) && Boolean.valueOf(path[pathIndex][1]))==resultForOpts){
            	
            	System.out.println(urlToTestOpts + " PASSED");
            	
        }else{
        	//this means that the expected is not equal to the tested val; FAILURE
                System.out.println(urlToTestOpts + " FAILED");
                verify = false;
        }
	   	
	   	}
		assertTrue(verify);
   	}
   	/**
    	* Create set of tests by taking the testUrlXXX arrays and
    	* running through all possible permutations of their combinations.
    	*
    	* @param testObjects Used to create a url.
    	*/

   	//scheme possibilities
      String[][] scheme = {{"http://", "true"},
           {"ftp://", "true"},
           {"http:/", "false"},
           {"http:", "false"},
           {"http/", "false"},
           {"://", "false"},
           {"", "true"}};

     	//auth possibilities; ips, urls

        String[][] authority = {{"www.google.com", "true"},
            {"oregonstate.edu", "true"},
            {"facebook.com", "true"},
            {"0.0.0.0", "true"},
            {"255.255.255.255", "true"},
            {"256.256.256.256", "false"},
            {"", "false"}
        };
        
       	//port possibilities; numbers, letters

        String[][] port = {{":80", "true"},
                 {":65535", "true"},
                 {":0", "true"},
                 {":-1", "false"},
                 {":65a", "false"},
                 {":65636", "true"},
                 {"", "true"}

        };
        
        
       	//path possibilities

        String[][] path = {{"/test1", "true"},
                        {"/t123", "true"},
                        {"/$23", "true"},
                        {"/..", "false"},
                        {"/../", "false"},
                        {"/t1/", "true"},
                        {"/..//file", "false"},
                        {"/t1//file", "false"},
                        {"", "true"}

        };

        
       	//path options possibilities; slashes, dots, characters

        String[][] pathOptions = {{"/test1", "true"},
               {"/s123", "true"},
               {"/$234", "true"},
               {"/..", "false"},
               {"/../", "false"},
               {"/test1/", "true"},
               {"/#", "false"},
               {"/s1/file", "true"},
               {"/s123/file", "true"},
               {"/$234/file", "true"},
               {"/../file", "false"},
               {"/..//file", "false"},
               {"/#/file", "false"},
               {"", "true"}

        };

        
        
       	//query possibilities

        String[][] query = {{"?action=view", "true"},
          {"?action=edit&mode=up", "true"},
          {"", "true"}
        };

}
